学校的算法作业,感觉题还不错就写一下了 by HIT_李·家蜂皇浆
题目:某工厂收到n 个订单(ai,bi),其中ai 和bi 均是正整数(1<=i<=n), 订单(ai,bi)希望在时间bi 之前获得ai 件产品。工厂的生产能力为每个时间单位生产1 件产品。
工厂希望拒绝最少数量的订单,并恰当地排序剩下的订单使得剩下的订单均能够被满足。试设计一个贪心算法求解上述问题。
解:
最晚开始时间:对任意订单,如果要对其进行生产,最晚开始进行的时间。区间e表示已选任务所占用的生产时间(均按每个任务的最晚时间进行编排),此时,任务的最晚开始时间就是排除区间e后,最晚开始进行的时间。
贪心思想:初始排除区间为e,将所有订单在区间e的时间不能生产的情况下,每个订单最晚开始时间排序,每次选择最晚开始时间最大的订单,并将该订单在排除区间e后所需要的最晚加工时间段加入排除区间e。
贪心选择性:将所有订单在区间e的时间不能生产的情况下,每个订单最晚开始时间排序,设任务pi是最晚开始时间最大的任务,那么必有一个优化解包含任务pi。
证明:设订单集合为(p1,p2,……,pn),排除区间为e。S是该订单问题的优化解。
若S包含任务pi,得证。
引理1:S是该订单问题的优化解。设S中的订单中最晚结束时间(即bi)最大的任务为s1(ai,bi)。则可以让工厂在时间段(bi -ai,bi)中生产这个订单的产品,使 得其它订单可正常完成。
否则,设时间分配方案为t,该任务生产区间为ti,则ti中的所有生产时间都在bi前,否则无法完成任务s1。此时,可将ti中的与(bi -ai,bi)中的任务进行调换,则 原本在(bi -ai,bi)时间内完成的任务工作时间提前了,并不影响生产。
若S不包含任务pi(ai,bi),设S中的订单中最晚结束时间(即b)最大的任务为s1(aj,bj)。则可以让工厂在时间段(bj–aj,bj)中生产这个订单的产品,使得其它订单可正常完成。则由于pi的选取规则,必有bj-aj< bi- ai,所以可以用任务pi替换任务s1,使得任务pi在时间段(bi-ai,bi)内完成,该任务与其他任务没有冲突,则新生成的任务集S’也是该问题的优化解
优化子结构:将所有订单在区间e的时间不能生产的情况下,订单问题的优化解是S,此时,S中的订单最晚开始时间的任务是s1,此时任务s1的生产区间为t(t可能不连续,因为e可能不连续),令e’=e+t,则S-s1是余下订单中,任务区间e’不能生产的情况下,任务选择的优化解。
task(S)
typedefstruct job{
start;
interregion;
}//记录任务最晚开始时间及在此时的任务生产时间段
e=null;job*S’;result;
fori=1 to length(S) do
S’[i]=resetJob(e,S[i]);//resetJob(e,s)排除区间e后任务s最晚开始时间及生产区间
while(S’!=null)
s=findMaxStart(S’);
result+=s; e+=s.interregion; S’-=s;//重设e,将s从S’中剔除
n=length(S’)
fori=1 to n do
S’[i]=resetJob(e,S’[i]);
forl in S’ do
ifl.start <0 then
S’-=s;
returnresult;
也可以用递归来完成
task2(s,e)
resetJob(e,S[i]);//resetJob(e,s)排除区间e后任务s最晚开始时间及生产区间,并进行排序,将最晚开始时间小于0的订单都剔除
print(S[1]);e+=S[i].interregion; 从S中删除S[1];
task2(S,e)